﻿package net.jmp0.toast.levels 
{
	import flash.utils.ByteArray;
	import net.jmp0.toast.entities.bases.GameElement;
	import net.jmp0.toast.entities.effects.HUD;
	import net.jmp0.toast.entities.obstacles.Banana;
	import net.jmp0.toast.entities.obstacles.GameKey;
	import net.jmp0.toast.entities.obstacles.Goal;
	import net.jmp0.toast.entities.obstacles.Lock;
	import net.jmp0.toast.entities.obstacles.MagicOrange;
	import net.jmp0.toast.entities.obstacles.Pushable;
	import net.jmp0.toast.entities.obstacles.StandardWall;
	import net.jmp0.toast.entities.obstacles.Teleporter;
	import net.jmp0.toast.entities.obstacles.Toaster;
	import net.jmp0.toast.entities.player.MouseControl;
	import net.jmp0.toast.entities.player.Player;
	import punk.Backdrop;
	import punk.core.World;

	
	/**
	 * 
	 * @author Thodd
	 */
	public class GameLevel extends World {
		
		//Background
		[Embed(source = '../res/karosheet.png')]private var imgBackgroundKaro:Class;
		private var backgroundKaro:Backdrop = new Backdrop(imgBackgroundKaro, 0, 0, true, true);
		[Embed(source = '../res/coffee_stain_splash.png')]private var imgBackgroundStainSplash:Class;
		private var backgroundStainSplash:Backdrop = new Backdrop(imgBackgroundStainSplash, 0, 0, false, false);
		[Embed(source = '../res/coffee_stain_big.png')]private var imgBackgroundStainBig:Class;
		private var backgroundStainBig:Backdrop = new Backdrop(imgBackgroundStainBig, 0, 0, false, false);
		
		//Fonts
		[Embed(source = '../res/take_out_the_garbage.ttf', fontFamily = 'garbage')] private var fontGarbage:Class;

		//Levelmetadata
		private var tilesize:int = 20;
		
		//Teleporterlist, used to determine which teleporter maps to which
		private var teleporters:Array = new Array();

		//MouseControl Instance
		private var mouseControl:MouseControl;
		
		//This variable holds a reference to a XML File containing the level information
		private var currentLevel:XML;
		
		private var password:String;
		private var title:String = "Generic Level Title";
		
		
		public function GameLevel(newLevel:XML) {
			//Jump to a specific level through constructor
			this.currentLevel = newLevel;
		}
		
		/**
		 * Initialising the Level
		 */
		override public function init():void {
			
			//Background setup
			setupBackgroundDecals();
			
			//Create the Level
			createLevelFromXML(this.currentLevel);
			
			//Mapping the Teleporters on each other (if there are any)
			mapTelepartners();
			
			//HUD Texts
			this.add(new HUD());
			
			//Get MouseControl
			mouseControl = new MouseControl();
	
		}
		
		
		/**
		 * Just setting up some coffee stain "decals"
		 */
		private function setupBackgroundDecals():void {
			FP.screen.color = 0xFFFFFF;
			backgroundKaro.depth = 100000;
			backgroundStainSplash.depth = 10000;
			backgroundStainBig.depth = 10000;
			
			backgroundStainSplash.x = 420;
			backgroundStainSplash.y = 0;
			
			backgroundStainBig.x = -20;
			backgroundStainBig.y = 340;
			
			this.add(backgroundKaro);
			this.add(backgroundStainSplash);
			this.add(backgroundStainBig);
		}
		
		
		/**
		 * Parsing a XML File and creating objects according to the tags found in the *.xml
		 * @param	xmlData the level information represented by a XML object
		 */
		private function createLevelFromXML(xmlData:XML):void {
			
			this.password = xmlData.@password;
			this.title = xmlData.@title;
			
			var o:XML;
			for each (o in xmlData.elements[0].wall) {
				this.add( new StandardWall(o.@x * this.tilesize, o.@y * this.tilesize));
			}
			
			for each (o in xmlData.elements[0].banana) {
				this.add( new Banana(o.@x * this.tilesize, o.@y * this.tilesize, o.@xDir, o.@yDir));
			}
			
			for each (o in xmlData.elements[0].toaster) {
				this.add( new Toaster(o.@x * this.tilesize, o.@y * this.tilesize, o.@xDir, o.@yDir));
			}
			
			for each (o in xmlData.elements[0].toast) {
				this.add( new Player(o.@x * this.tilesize, o.@y * this.tilesize));
			}
			
			for each (o in xmlData.elements[0].teleporter) {
				var t:Teleporter = new Teleporter(o.@x * this.tilesize, o.@y * this.tilesize, o.@color);
				this.add(t);
				//Important! The teleporter reference needs to be saved,
				//used to map the teleporters on eachother
				teleporters.push(t); 
			}
			
			for each (o in xmlData.elements[0].key) {
				this.add(new GameKey(o.@x * this.tilesize, o.@y * this.tilesize,  o.@amount));
			}
			
			for each (o in xmlData.elements[0].lock) {
				this.add(new Lock(o.@x * this.tilesize, o.@y * this.tilesize));
			}
			
			for each (o in xmlData.elements[0].orange) {
				this.add(new MagicOrange(o.@x * this.tilesize, o.@y * this.tilesize,  o.@amount));
			}
			
			for each (o in xmlData.elements[0].pushable) {
				this.add(new Pushable(o.@x * this.tilesize, o.@y * this.tilesize));
			}
			
			for each (o in xmlData.elements[0].goal) {
				this.add(new Goal(o.@x * this.tilesize, o.@y * this.tilesize,  o.@message));
			}
			
		}
		
		
		/**
		 * Super wierd code... this callback stuff confuses me...
		 * This method sucks, but as always i'm too lazy to clean it up.
		 * Anyway this method maps the teleporters on each other
		 */
		private function mapTelepartners():void {
			function f(item:Teleporter, index:int, array:Array):void {
				function p(item:Teleporter, index:int, array:Array):void {
					if (item != this && item.getColor() == this.getColor()) {
						item.setTelepartner(this);
						this.setTelepartner(item);
						trace(""+item.getID() + " found " + this.getID());
					}
				}
				teleporters.forEach(p,item);
			}
			
			teleporters.forEach(f);
		}
		
		/**
		 * Returns the MouseControl object associated with the level this function is called on
		 * @return the MouseControl object responsible for this level
		 */
		public function getMouseControl():MouseControl {
			return mouseControl;
		}
		
		public function restartLevel():void {
			FP.goto = new GameLevel(this.currentLevel);
		}
		
	}

}